import axios from 'axios'
import { ElMessage } from 'element-plus'
// import store from '@/store'
import { loginApi } from '@/api/api'
import { getToken } from '@/utils/auth'
import CryptoJS from 'crypto-js'

import router from '@/router'
import { useUserStore } from '@/store/user'; // pinia token引入
import { qiankunWindow } from 'vite-plugin-qiankun/dist/helper'

// 缓存请求的数组
let cacheRequestArr = []

// 将请求都push到数组中,数组是[function(token){}, function(token){},...]
function cacheRequestArrHandle(cb) {
  cacheRequestArr.push(cb)
}

// 数组中的请求得到新的token之后执行，用新的token去重新发起请求
function afreshRequest(token) {
  cacheRequestArr.map((cb) => cb(token))
  cacheRequestArr = []
}

// 获取sign签名
function getSign(signBefore) {
  const arr = ['appSecret', 'timestamp', 'nonceStr', 'token', 'body']
  let str = ''
  arr.forEach((item) => {
    const value = signBefore[item]
    if (!value) {
      return
    } else {
      str += `&${item}=${signBefore[item]}`
    }
  })
  return CryptoJS.MD5(str.substr(1)).toString()
}

// 是否为开发环境
const isDev = process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'test' // 是否是开发环境
// console.log(process.env.VUE_APP_BASE_API)
// create an axios instance
const service = axios.create({
  baseURL: 'http://test-api-gw.964yx.com', // url = base url + request url
  // withCredentials: true, // send cookies when cross-domain requests
  timeout: 10000 // request timeout
})
service.interceptors.request.use(
  (config) => {
    let appId, appSecret, nonceStr
    if (isDev) {
      appId = '4m6BmtDs'
      appSecret = '735477bafe10bcae951a8c38a1ee83ed2cfc5879'
      nonceStr = 'YlBimsAdmin'
    } else {
      appId = 'oOSR4h2M'
      appSecret = '9bf373851dc21bd3c9e1d09add23929b5e09fd34'
      nonceStr = 'YlBimsAdmin'
    }
    const timestamp = Date.now()
    config.headers['app_id'] = appId
    config.headers['timestamp'] = timestamp
    config.headers['nonce_str'] = nonceStr
    const signBefore = {
      appSecret,
      timestamp,
      nonceStr
    }
    // 获取pinia的方法及数据
    const userInfo = useUserStore()
    const body = JSON.stringify(config.data)
    // console.log('body', body)
    if (body != undefined && body.length > 0) {
      // base64
      var words = CryptoJS.enc.Utf8.parse(body)
      var base64 = CryptoJS.enc.Base64.stringify(words)
      signBefore.body = base64
    }

    if (userInfo.token || getToken()[0]) {
      // console.log('我有token')
      config.headers['token'] = getToken()[0]
      signBefore.token = getToken()[0]
      const now = new Date().getTime()
      const tokenExpTime = getToken()[3]
      if ((!tokenExpTime || tokenExpTime < now) && config.url !== loginApi.sessionRefresh) {
        // console.log(config.url + '时token过期')
        // 将请求缓存起来
        // console.log('缓存' + config.url + '的请求')
        const retry = new Promise((resolve) => {
          cacheRequestArrHandle((token) => {
            signBefore.token = token
            const sign = getSign(signBefore)
            config.headers['sign'] = sign
            config.headers['token'] = token // token为刷新完成后传入的token
            // console.log('开始执行缓存的请求' + config.url + '--token是' + token)
            resolve(config)
          })
        })

        if (!userInfo.isRefreshing) {
          // debugger
          // 开始刷新token，刷新会话
          // console.log('开始刷新')
          userInfo.loginSessionRefresh('user/sessionRefresh')
            .then(() => {
              // console.log('刷新成功')
              // 刷新token完成后重新请求之前的请求
              afreshRequest(getToken()[0])
            })
            .catch(() => {
              // 刷新token失败，跳转登陆页
              cacheRequestArr = []
              userInfo.resetToken('user/resetToken').then(() => {
                router.push({ path: '/login' })
              })
            })
        }
        return retry
      }
    }
    const sign = getSign(signBefore)
    config.headers['sign'] = sign

    return config
  },
  (error) => {
    // do something with request error
    console.log(error) // for debug
    return Promise.reject(error)
  }
)

// response interceptor
service.interceptors.response.use(
  /**
   * If you want to get http information such as headers or status
   * Please return  response => response
   */

  /**
   * Determine the request status by custom code
   * Here is just an example
   * You can also judge the status by HTTP Status Code
   */
  (response) => {
    const res = response.data
    const userInfo = useUserStore()
    const {
      config
    } = response
    // 不校验code是否为1，直接把交给页面去处理
    if (config.unCheckCode) {
      return res
    }
    // if the custom code is not 1, it is judged as an error.
    if (res.code !== 1) {
      // token无效
      if (res.code === 1003 || res.code === 1004 || res.code === 1005) {
        // 对所有做置空操作
        userInfo.resetToken('user/resetToken').then(() => {

          if (qiankunWindow.__POWERED_BY_QIANKUN__) {
            const microMode = useMicro()
            const { setGlobalState } = microMode
            //token  失效回调主应用 登录
            setGlobalState({
              actionKey: '1001'
            })
          } else {
            setTimeout(() => {
              router.push({ path: '/login' })
            }, 1000)
          }
          ElMessage({
            message: '登录状态失效，请重新登录',
            type: 'error',
            duration: 2.5 * 1000
          })
        })

        return
      }
      const msg = res.code === -1 ? '服务器繁忙,请稍后再试' : res.msg || 'Error'
      ElMessage({
        message: msg,
        type: 'error',
        duration: 2.5 * 1000
      })
      return Promise.reject()
    } else {
      return res
    }
  },
  (error) => {
    console.log('err' + error) // for debug
    ElMessage({
      message: error.message || 'Error',
      type: 'error',
      duration: 2.5 * 1000
    })
    return Promise.reject(error)
  }
)

function request(url, data = {}, {
  method = 'post',
  unCheckCode = false
} = {}) {
  return service({
    url,
    data,
    method,
    unCheckCode
  })
}


export default request